<?php

class FP_Model {

    protected $_data = array();
    protected $_gateway = null;

    protected $_errors = array();
    protected $_validation_options = array(
			'inputNamespace' => 'FP_Validation',
			'breakChainOnFailure' => false
			);
    protected $_validation_filters = array('*' => 'StringTrim');
    protected $_validators = array();

    public function validate(array $pData=null){

	if ($pData)
	$data = $pData;
	else
	$data = $this->_data;

	$validator = new Zend_Filter_Input($this->_validation_filters, $this->_validators, $data, $this->_validation_options);
	if (!$validator->isValid())
	$this->_errors = array_merge($this->_errors, $validator->getMessages());

	if (count($this->_errors) > 0){

	$validation_errors = array();
	foreach ($this->_errors as $field => $error){
	    if (is_array($error)){
	    foreach ($error as $validator => $message)
		$validation_errors[$field] = "{$field}: {$message}";
	    } else
	    $validation_errors[$field] = "{$field}: {$error}";
	}
	$this->_errors = array();
	throw new FP_Validation_Exception('Object validation failed ' . logobject($validation_errors), null, $validation_errors);
	}
	return true;
    }

    public function __construct(array $pData, $pGateway){
	$this->setGateway($pGateway);
	$this->import($pData);
    }

    public function __set($pAtt, $pVal){
	if (array_key_exists($pAtt, $this->_data))
	    $this->_data[$pAtt] = $pVal;
    }

    public function __get($pAtt){
	switch ($pAtt){
	case 'gateway':
	return $this->getGateway();
	default:
	if (array_key_exists($pAtt, $this->_data))
	    if (is_string($this->_data[$pAtt]))
		return stripslashes($this->_data[$pAtt]);
	    else
		return $this->_data[$pAtt];
	else
	    throw new Exception("Invalid attribute - ". get_class($this) ."->$pAtt");
	}
    }

    public function __isset($pAtt){
	if (array_key_exists($pAtt, $this->_data))
	return isset($this->_data[$pAtt]);
	else
	return false;
    }

    public function __unset($pAtt){
	if (array_key_exists($pAtt, $this->_data))
	unset($this->_data[$pAtt]);
	else
	return null;
    }

    public function import(array $pData){
	//$pData = $this->_convert($pData);

	foreach ($pData as $key => $val)
	$this->__set($key, $val);

	return $this;
    }

    public function save($pValidate=true){
	if ($pValidate)
	    $this->validate();

	$this->_data = $this->gateway->save($this->_data);
	return true;
    }

    public function delete(){
	return $this->gateway->delete($this);
    }

    public function setGateway($pGateway){
	$this->_gateway = $pGateway;
	return $this;
    }

    public function getGateway(){
	return $this->_gateway;
    }

    public function toArray(){
	return $this->_data;
    }

    protected function _convert($pData){
	if (is_array($pData))
	return $pData;
	else if (is_object($pData))
	return (array) $pData;
	else
	throw new Exception("Data must be an datasource, array or object");
    }

    public function __call($pMethod, $pArgs){

	if (preg_match('/^get(.*)/', $pMethod, $matches)){   //dynamically get lazy loaded properties from gateway (ie, getComments, getProfile)

	    $var = '_' . from_camel_case($matches[1]);

	    if (property_exists($this, $var)){
		if ($this->$var === null || (array_key_exists(0, $pArgs) && $pArgs[0])){ //If first argument is true, this will refresh to call to get property from gateway

		    $val = call_user_func(array($this->gateway, $pMethod), $this);
		    $this->$var =  $val;
		}

		return $this->$var;
	    } else
		throw new Exception("Referenced Invalid property {$var}");
	}

    }

}

?>